import socket
import threading
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
from tkinter import filedialog
import os
import struct

class ServerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Server")

        self.text_area = ScrolledText(root, wrap=tk.WORD, state='disabled', width=50, height=20)
        self.text_area.pack(padx=10, pady=10)

        self.entry_message = tk.Entry(root, width=40)
        self.entry_message.pack(padx=10, pady=5, side=tk.LEFT)
        self.entry_message.bind("<Return>", lambda event: self.send_message())  # 绑定Enter键

        self.send_button = tk.Button(root, text="Send", command=self.send_message)
        self.send_button.pack(padx=10, pady=5, side=tk.LEFT)

        self.file_button = tk.Button(root, text="Send File", command=self.send_file)
        self.file_button.pack(padx=10, pady=5, side=tk.LEFT)

        self.exit_button = tk.Button(root, text="Exit", command=root.quit)
        self.exit_button.pack(padx=10, pady=5, side=tk.LEFT)

        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.bind(('0.0.0.0', 12345))  # 使用0.0.0.0以便监听所有IP地址
        self.server_socket.listen(1)

        self.client_socket = None
        self.client_address = None

        self.accept_thread = threading.Thread(target=self.accept_connection)
        self.accept_thread.start()

    def accept_connection(self):
        self.client_socket, self.client_address = self.server_socket.accept()
        self.display_message(f"New client connected: {self.client_address}\n")
        self.receive_thread = threading.Thread(target=self.receive_messages)
        self.receive_thread.start()

    def send_message(self):
        if self.client_socket:
            message = self.entry_message.get()
            if message:
                self.client_socket.sendall(message.encode())
                self.entry_message.delete(0, tk.END)
                self.display_message(f"Server: {message}\n")
                if message.lower() == 'exit':
                    self.root.quit()

    def send_file(self):
        if self.client_socket:
            file_path = filedialog.askopenfilename()
            if file_path:
                file_name = os.path.basename(file_path)
                file_size = os.path.getsize(file_path)
                self.client_socket.sendall(b"FILE" + struct.pack("Q", file_size) + file_name.encode() + b'\0')
                with open(file_path, 'rb') as file:
                    while (chunk := file.read(1024)):
                        self.client_socket.sendall(chunk)
                self.display_message(f"File sent: {file_path}\n")

    def receive_messages(self):
        while True:
            data = self.client_socket.recv(1024)
            if not data:
                break
            if data.startswith(b"FILE"):
                file_size, file_name = struct.unpack("Q", data[4:12])[0], data[12:].split(b'\0', 1)[0].decode()
                self.receive_file(file_size, file_name)
            else:
                message = data.decode()
                self.display_message(f"Client: {message}\n")

    def receive_file(self, file_size, file_name):
        received_size = 0
        with open(file_name, 'wb') as file:
            while received_size < file_size:
                data = self.client_socket.recv(1024)
                if not data:
                    break
                file.write(data)
                received_size += len(data)
        self.display_message(f"File received: {file_name}\n")

    def display_message(self, message):
        self.text_area.config(state='normal')
        self.text_area.insert(tk.END, message)
        self.text_area.config(state='disabled')

if __name__ == "__main__":
    root = tk.Tk()
    app = ServerApp(root)
    root.mainloop()